﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Ninject;
using SomeRandomGame.Interfaces;

namespace SomeRandomGame.Screens
{
    public abstract class MenuScreenBase: GameScreen
    {
        private IList<MenuEntry> _menuEntries = new List<MenuEntry>();
        private int _selectedEntry = 0;
        private string _menuTitle;
        private IGameManager _gameManager;

        protected IList<MenuEntry> MenuEntries
        {
            get { return _menuEntries; }
        }

        protected MenuScreenBase( IGameManager gameManager, string menuTitle )
        {
            _menuTitle = menuTitle;
            _gameManager = gameManager;

            TransitioningInTime = TimeSpan.FromSeconds( 0.5 );
            TransitioningOutTime = TimeSpan.FromSeconds( 0.5 );
        }

        public override void HandleInput( IInputManager inputManager )
        {
            if( inputManager.IsMenuUp( ControllingPlayer ) )
            {
                _selectedEntry--;

                if( _selectedEntry < 0 )
                {
                    _selectedEntry = _menuEntries.Count - 1;
                }
            }

            if( inputManager.IsMenuDown( ControllingPlayer ) )
            {
                _selectedEntry++;

                if( _selectedEntry >= _menuEntries.Count )
                {
                    _selectedEntry = 0;
                }
            }

            PlayerIndex playerIndex = ControllingPlayer.HasValue ? ControllingPlayer.Value : PlayerIndex.One;

            if( inputManager.IsMenuSelect( ControllingPlayer ) )
            {
                OnSelectEntry( _selectedEntry, playerIndex );
            }
            else if( inputManager.IsMenuCancel( ControllingPlayer ) )
            {
                OnCancel( playerIndex );
            }
        }

        protected virtual void OnSelectEntry( int entryIndex, PlayerIndex playerIndex )
        {
            _menuEntries[entryIndex].OnSelectEntry( playerIndex );
        }

        protected virtual void OnCancel( PlayerIndex playerIndex )
        {
            ExitScreen();
        }

        protected void OnCancel( object sender, PlayerIndexEventArgs e )
        {
            OnCancel( e.PlayerIndex );
        }

        protected virtual void UpdateMenuEntryLocations()
        {
            float transitionOffset = (float)Math.Pow( TransitionPosition, 2 );

            // start position
            Vector2 position = new Vector2( 0f, 175f );

            for( int i = 0; i < _menuEntries.Count; i++ )
            {
                MenuEntry menuEntry = _menuEntries[i];

                // each entry is to be centered horizontally
                position.X = _gameManager.Game.GraphicsDevice.Viewport.Width / 2 - menuEntry.Width / 2;

                if( ScreenState == ScreenState.TransitioningIn )
                {
                    position.X += transitionOffset * 256;
                }
                else
                {
                    position.X -= transitionOffset * 512;
                }

                menuEntry.Position = position;
                position.Y += menuEntry.Height;
            }
        }

        public override void Update( GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen )
        {
            base.Update( gameTime, otherScreenHasFocus, coveredByOtherScreen );

            for( int i = 0; i < _menuEntries.Count; i++ )
            {
                bool isSelected = IsActive && _selectedEntry == i;

                _menuEntries[i].Update( this, isSelected, gameTime );
            }
        }

        public override void Draw( SpriteBatch spriteBatch, IGameManager gameManager, GameTime gameTime )
        {
            UpdateMenuEntryLocations();

            SpriteFont font = gameManager.ServiceLocator.Get<IContentFactory>().MenuFont;

            for( int i = 0; i < _menuEntries.Count; i++ )
            {
                MenuEntry menuEntry = _menuEntries[i];


                bool isSelected = IsActive && _selectedEntry == i;

                menuEntry.Draw( gameManager, this, spriteBatch, isSelected, gameTime );
            }

            // Draw the menu title centered on the screen
            Vector2 titlePosition = new Vector2( gameManager.Game.GraphicsDevice.Viewport.Width / 2, 80 );
            Vector2 titleOrigin = font.MeasureString( _menuTitle ) / 2;
            Color titleColor = new Color( 192, 192, 192 ) * TransitionAlpha;
            float titleScale = 1.25f;

            // Moving from the top to target position; Since the way is not too long the TransitionPosition-variable is weighted very high
            titlePosition.Y -= (float)Math.Pow( TransitionPosition, 2 ) * 100;

            spriteBatch.Begin();
            spriteBatch.DrawString( font, _menuTitle, titlePosition, titleColor, 0,
                                    titleOrigin, titleScale, SpriteEffects.None, 0 );
            spriteBatch.End();
        }
    }
}
